package com.fp.m7.dao;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;

import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.MongoRepository;

import com.fp.m7.api.util.Clock;
import com.fp.m7.model.HasDate;

public class BaseDaoImpl<T extends HasDate, R extends MongoRepository<T, ObjectId>>
		implements BaseDao<T> {

	protected R repository;

	@Autowired
	protected MongoTemplate template;

	private static Validator validator = Validation
			.buildDefaultValidatorFactory().getValidator();

	@Autowired
	protected Clock clock;

	@Override
	public T findById(ObjectId id) {
		return repository.findOne(id);
	}

	@Override
	public T save(T object) {
		prePersist(object);
		return update(object);
	}

	@Override
	public T update(T object) {
		validate(object);
		return repository.save(object);
	}

	@Override
	public void delete(T object) {
		repository.delete(object);
	}

	protected void prePersist(T object) {
		object.setDate(clock.getDateAsLong());
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	protected void validate(T object) {
		Set<ConstraintViolation<T>> errors = validator.validate(object);
		if (!errors.isEmpty()) {
			throw new ConstraintViolationException((Set) errors);
		}
	}

	public void setRepository(R repository) {
		this.repository = repository;
	}

	public void setTemplate(MongoTemplate template) {
		this.template = template;
	}

	public void setClock(Clock clock) {
		this.clock = clock;
	}
}
